<template>
  <div class="box clearfix"
    v-loading="loadingWs"
    :element-loading-text="loadingText"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(0, 0, 0, 0.6)"
  >
    <div class="box_title">
      <span>机器运行时间：<i><el-tag effect="dark" type="success">{{ RUN_TIME }}</el-tag></i></span>
      <span>当前连接用户数：<i><el-tag effect="dark" type="warning">{{ USER_SIZE }}</el-tag></i></span>
    </div>
    <div class="box_card clearfix">
      <div class="box_card_item">
        <el-card class="card" shadow="always">
          <span class="header">
            <i class="el-icon-star-off" style="color:#ffba00"></i>
            <span>内存</span>
          </span>
          <el-table
            :data="tableData"
            border
            height="120"
          >
            <el-table-column
              prop="type"
              label="类型"
              width="80">
            </el-table-column>
            <el-table-column
              prop="size"
              label="内存大小"
              width="80">
            </el-table-column>
            <el-table-column
              prop="used"
              width="80"
              label="已使用">
            </el-table-column>
            <el-table-column
              prop="per"
              label="使用率">
              <template slot-scope="scope">
                <el-progress :text-inside="true" :stroke-width="20" :percentage="scope.row.per"></el-progress>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </div>
      <div class="box_card_item">
        <el-card class="card" shadow="always">
          <span class="header">
            <i class="el-icon-c-scale-to-original" style="color:#1890ff"></i>
            <span>硬盘</span>
          </span>
          <el-table
            :data="tableDataDisk"
            border
            height="120"
          >
            <el-table-column
              prop="path"
              label="文件系统"
              :show-overflow-tooltip="true"
              width="80">
            </el-table-column>
            <el-table-column
              prop="mountPoint"
              label="挂载路径"
              :show-overflow-tooltip="true"
              width="80">
            </el-table-column>
            <el-table-column
              prop="total"
              label="硬盘大小"
              width="80">
            </el-table-column>
            <el-table-column
              prop="used"
              width="60"
              :show-overflow-tooltip="true"
              label="已使用">
            </el-table-column>
            <el-table-column
              prop="per"
              label="使用率">
              <template slot-scope="scope">
                <el-progress :text-inside="true" :stroke-width="20" :percentage="scope.row.per"></el-progress>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </div>
      <div class="box_card_item screen_all">
        <el-card class="card" shadow="always">
          <span class="header">
            <i class="el-icon-attract" style="color:#13ce66"></i>
            <span>CPU</span>
          </span>
          <div class="echarts">
            <chart-view :chartOption="cpuCharts.chartOpt" :height="cpuCharts.height" :clear-chart="false" :auto-resize="true" :play-highlight="cpuCharts.playHighlight" />
          </div>
        </el-card>
      </div>
      <div class="box_card_item screen_all">
        <el-card class="card" shadow="always">
          <span class="header">
            <i class="el-icon-magic-stick" style="color:red"></i>
            <span>进程</span>
          </span>
          <div class="echarts">
            <el-progress
            v-for="item in progressData"
            :key="item.id"
            :type="item.type || 'circle'" :percentage="item.percentage" :format="format.bind(null,item)"></el-progress>
          </div>
        </el-card>
      </div>
    </div>
  </div>
</template>

<script>
import 'echarts/lib/chart/gauge'
import 'echarts/lib/chart/line'
import 'echarts/lib/component/dataZoom'

import { getDuration, bFormatterTo} from '@/utils/util.js'
  export default {
    name: 'OverviewTable',
    props: {
      data: {
        type: Object,
        default: () => ({
          socketURI:'',
        })
      },
    },
    data () {
      return {
        socket: '',
        loadingText: '初始化……',
        loadingWs: true,
        RUN_TIME: null, //运⾏时间,秒
        USER_SIZE: 0, //⽤户数
        tableData: [],
        tableDataDisk: [],
        setChartTimeFlag: false,
        cpuCharts: {
            id: '333',
            title:'cpu占用率',
            width: '100%',
            height: '200px',
            playHighlight: false,
            chartOpt: {
              tooltip : {
                trigger: 'item',
                formatter: "{a} <br/>{b} : {c}%"
              },
              legend: {
                textStyle: {color: '#333'},
                x: '20%', // 'center' | 'left' | {number},
                y: 'top', // 'center' | 'bottom' | {number}
                data:['cpu运行轨迹']
              },
              calculable : true,
              grid: {
                x: '20%',
                y: 40,
                x2: 65,
                y2: 50,
                borderWidth: 1,
              },
              xAxis :
                {
                  type: "category", // 这里使用时间轴模式
                  splitLine : {
                    show : true,//是否显示网格线
                  },
                  "axisLine": {
                      lineStyle: {
                          color: '#90979c'
                      }
                  },
                  axisLabel : {
                    show:true,
                    interval: 'auto',    // {number}
                    rotate: 10,
                    margin: 6,
                    // formatter: function(value, index) {
                    //   return value.split(' ')[1]
                    // },
                    textStyle: {
                      color: '#333',
                      fontFamily: 'sans-serif',
                      fontSize: 10,
                      fontStyle: 'italic',
                    }
                  },
                  name:"时间",
                  axisPointer: {
                      type: 'shadow'
                  },
                  data : [],
              }
              ,
              yAxis : [
                {
                  type : 'value',
                  position:'right',
                  name:"单位（%）",
                  splitLine: {
                    show: true,//是否显示网格线
                  },
                  min: 0,
                  max: 100,
                  axisLabel : {
                    show:true,
                    interval: 'auto',    // {number}
                    // rotate: -45,
                    // margin: 18,
                    // formatter: '{value} ml',    // Template formatter!
                    // textStyle: {
                    //   color: '#1e90ff',
                    //   fontFamily: 'verdana',
                    //   fontSize: 10,
                    //   fontStyle: 'normal',
                    //   fontWeight: 'bold'
                    // }
                  },
                }
              ],
              dataZoom: [{
                show: true,
                realtime: true,
                start: 0,
                end: 100,
                height: 15,
                bottom: 10,
              }],
              series : [
                {
                    name:'CPU状态',
                    type:'gauge',
                    center : ['10%', '50%'],    // 默认全局居中
                    radius : '80%',
                    min:0,
                    max:100,
                    splitNumber:5,
                    axisLine: {            // 坐标轴线
                      lineStyle: {       // 属性lineStyle控制线条样式
                        color: [[0.09, 'lime'],[0.82, '#1e90ff'],[1, '#ff4500']],
                        width: 2,
                        shadowColor : '#eee', //默认透明
                        shadowBlur: 6
                      }
                    },
                    axisLabel: {            // 坐标轴小标记
                      textStyle: {       // 属性lineStyle控制线条样式
                        color: '#333',
                        shadowColor : '#333', //默认透明
                        shadowBlur: 6
                      }
                    },
                    axisTick: {            // 坐标轴小标记
                      length :8,        // 属性length控制线长
                      lineStyle: {       // 属性lineStyle控制线条样式
                        color: 'auto',
                        shadowColor : '#fff', //默认透明
                        shadowBlur: 6
                      }
                    },
                    splitLine: {           // 分隔线
                      length :15,         // 属性length控制线长
                      lineStyle: {       // 属性lineStyle（详见lineStyle）控制线条样式
                        width:2,
                        color: '#1e90ff',
                        shadowColor : '#eee', //默认透明
                        shadowBlur: 6
                      }
                    },
                    pointer: {           // 分隔线
                      shadowColor : '#ccc', //默认透明
                      shadowBlur: 3
                    },
                    title : {
                      textStyle: {       // 其余属性默认使用全局文本样式，详见TEXTSTYLE
                        fontSize: 12,
                        fontStyle: 'italic',
                        color: '#333',
                        shadowColor : '#333', //默认透明
                        shadowBlur: 5
                      }
                    },
                    detail : {
                      // backgroundColor: 'rgba(30,144,255,0.8)',
                      // borderWidth: 1,
                      borderColor: '#333',
                      shadowColor : '#fff', //默认透明
                      shadowBlur: 5,
                      offsetCenter: [0, '90%'],       // x, y，单位px
                      textStyle: {       // 其余属性默认使用全局文本样式，详见TEXTSTYLE
                        fontWeight: 'bolder',
                        color: '#333'
                      },
                      formatter:'{value}%'
                    },
                    data:[{value: 0, name: '使用率'}]
                },
                {
                    name:'cpu运行轨迹',
                    type:'line',
                    data:[],
                    smooth: true,
                    boundaryGap: true,
                    markPoint : {
                      data : [
                        {type : 'max', name: '最大值'},
                        {type : 'min', name: '最小值'}
                      ]
                    },
                    markLine : {
                      data : [
                        {type : 'average', name: '平均值'}
                      ]
                    }
                },
              ]
            },
            data: []
        },
        progressData: []
      }
    },
    mounted() {
      this.initSocket()
    },
    beforeDestroy() {
      this.socket && this.socket.close();
    },
    methods: {
      format(record,percentage) {
        return `${record.text}:${record.number}`;
      },

      initSocket() {
        // 2.webSocket初始化
        if (this.data.socketURI === '') return;
        this.socket = new WebSocket(this.data.socketURI);
        this.socketOnOpen()
        this.socketOnMessage()
        this.socketOnClose()
        this.socketOnError()
      },
      socketOnMessage () {
        this.socket.onmessage = (e) => {
          const data = JSON.parse(e.data);
          switch(data.type){
            case 'Status':
              const sshStatus = JSON.parse(data.data).sshStatus
              const msg = JSON.parse(data.data).msg
              this.loadingText = msg
              if(sshStatus === 'CONNECTED'){
                // 成功
                this.loadingWs = false
              }else if(sshStatus === 'INIT'){
                // 初始化
                this.loadingText = '初始化……'
              }else if (sshStatus === 'CONNECTING') {
                // 连接中
                this.loadingText = `连接中……`
              }else if(sshStatus === 'ERROR') {
                this.loadingWs = true
                this.loadingText = msg
              }else if(sshStatus === 'FINISH'){
                // 失败
                this.$confirm(`连接失败，是否重连?`, '提示', {
                  confirmButtonText: '继续',
                  cancelButtonText: '取消',
                  type: 'warning'
                }).then(() => {
                  this.initSocket();
                }).catch(() => {
                  this.$message({
                    type: 'info',
                    message: '已取消重连'
                  });
                });
              }else {
                // 结束
                this.socketOnClose()
              }
              break
            case 'MonitorInfo':
              const tmp = JSON.parse(data.data)
              const d = tmp.info
              // RUN_TIME: 222.2, //运⾏时间,秒
              //   USER_SIZE: 3, //⽤户数
              //   TASK_TOTAL: 100, //总进程
              //   TASK_RUNNING: 30, //运⾏中
              //   TASK_SLEEPING: 5, //休眠
              //   TASK_STOPPED: 3, //停⽌
              //   TASK_ZOMBIE: 2, //僵⼫进程
              //   CPU_US: 2.2, //cpu使⽤率 百分制
              //   MEM_TOTAL: 100023, //内存总量 kb
              //   MEM_USED: 800, //内存使⽤ kb
              //   SWAP_TOTAL: 200, //swap 总量 kb
              //   SWAP_USED: 100, //swap使⽤ kb
              //   DISK_INFO: [ //磁盘信息
              //       {
              //           path: "/temp",// 文件系统
              //           mountPoint: "/temp",
              //           total: 999, //磁盘总量 kb
              //           used: 20, //使⽤量 kb
              //       }
              //   ]

              this.RUN_TIME = getDuration(parseFloat(d.RUN_TIME) * 1000)
              this.USER_SIZE = d.USER_SIZE
              this.tableData = [
                {
                  type: 'mem',
                  size: d.MEM_TOTAL ? bFormatterTo(d.MEM_TOTAL * 1024) : 0,
                  used: d.MEM_USED ? bFormatterTo(d.MEM_USED * 1024) : 0,
                  per: d.MEM_USED ? (d.MEM_USED / d.MEM_TOTAL * 100).toFixed(2) * 1 : 0,
                },
                {
                  type: 'swap',
                  size: d.SWAP_TOTAL ? bFormatterTo(d.SWAP_TOTAL * 1024) : 0,
                  used: d.SWAP_USED ? bFormatterTo(d.SWAP_USED * 1024) : 0,
                  per: d.SWAP_USED ? (d.SWAP_USED / d.SWAP_TOTAL * 100).toFixed(2) * 1 : 0,
                }
              ].sort((a,b) => b.per - a.per)
              this.tableDataDisk = d.DISK_INFO.length ? d.DISK_INFO.map(item => {
                item.per = item.used ? (item.used / item.total * 100).toFixed(2) * 1 : 0
                item.total = item.total ? bFormatterTo(item.total * 1024) : 0
                item.used = item.used ? bFormatterTo(item.used * 1024) : 0
                return item
              }).sort((a,b) => b.per - a.per) : []
              this.$set(this.cpuCharts.chartOpt.series[0],'data',[{value: d.CPU_US * 1, name: '使用率'}])

              if(this.cpuCharts.chartOpt.xAxis.data.length > 100){//超过设定的长度，删除一条数据
                this.cpuCharts.chartOpt.xAxis.data.shift();
                this.cpuCharts.chartOpt.series[1].data.shift();
              }
              const nowTime = new Date()
              this.cpuCharts.chartOpt.xAxis.data.push(this.getNowTime(nowTime))
              this.cpuCharts.chartOpt.series[1].data.push(d.CPU_US * 1)
              this.progressData =[{
                id: 'TASK_TOTAL',
                type:'circle',
                taskType: 'TASK_TOTAL',  //总进程
                percentage: d.TASK_TOTAL ? (d.TASK_TOTAL / d.TASK_TOTAL * 100).toFixed(2) * 1 : 0,
                number: d.TASK_TOTAL,
                text: '总进程',
              },{
                id: 'TASK_RUNNING',
                type:'circle',
                taskType: 'TASK_RUNNING',  //运⾏中
                percentage: d.TASK_RUNNING ? (d.TASK_RUNNING / d.TASK_TOTAL * 100).toFixed(2) * 1 : 0,
                number: d.TASK_RUNNING,
                text: '运⾏中',
              },{
                id: 'TASK_SLEEPING',
                type:'circle',
                taskType: 'TASK_SLEEPING',  //休眠
                percentage: d.TASK_SLEEPING ? (d.TASK_SLEEPING / d.TASK_TOTAL * 100).toFixed(2) * 1 : 0,
                number: d.TASK_SLEEPING,
                text: '休眠',
              },{
                id: 'TASK_STOPPED',
                type:'circle',
                taskType: 'TASK_STOPPED',  //停⽌
                percentage: d.TASK_STOPPED ? (d.TASK_STOPPED / d.TASK_TOTAL * 100).toFixed(2) * 1 : 0,
                number: d.TASK_STOPPED,
                text: '停⽌',
              },{
                id: 'TASK_ZOMBIE',
                type:'circle',
                taskType: 'TASK_ZOMBIE',  //僵⼫进程
                percentage: d.TASK_ZOMBIE ? (d.TASK_ZOMBIE / d.TASK_TOTAL * 100).toFixed(2) * 1 : 0,
                number: d.TASK_ZOMBIE,
                text: '僵⼫进程',
              },]
              break
            default:
            break
          }
        }
      },
      getNowTime(date) {
        let Hours = date.getHours();//获取当前小时数(0-23)
        let Minutes = date.getMinutes(); //获取当前分钟数(0-59)
        let Seconds = date.getSeconds();//获取当前秒数(0-59)
        let Milliseconds = date.getMilliseconds();//获取当前毫秒数(0-999)
        Hours = Hours < 10 ? `0${Hours}` : Hours
        Minutes = Minutes < 10 ? `0${Minutes}` : Minutes
        Seconds = Seconds < 10 ? `0${Seconds}` : Seconds
        return Hours + ":" + Minutes + ":" + Seconds
      },
      getTimeRange() {
        const now = new Date(); // 获取当前时间
        const timeRange = []; // 初始化时间范围数组
        for (let i = -10; i <= 10; i++) {
          // 计算前后10秒的时间
          const time = new Date(now.getTime() + i * 1000).toLocaleTimeString();
          timeRange.push(time);
        }
        return timeRange;
      },
      socketOnOpen() {
        this.socket.onopen = () => {
          this.socket.send(JSON.stringify({
              data:JSON.stringify({dataId: ~~this.data.id.split('_')[0]}),
              type: 'MonitorConn'
          }))
        }
      },
      socketOnClose() {
        this.socket.onclose = () => {}
      },
      socketOnError() {
        this.socket.onerror = () => {}
      },
    }
  }
</script>

<style lang="scss" scoped>
.box{
  padding:20px 0;
  overflow: auto;
  width:100%;
  height:100%;
  &_title{
    width:100%;
    display: flex;
    float: left;
    padding:0 0 20px 20px;
    span{
      font-size:16px;
      color:#333;
      padding-right:20px;
    }
  }
  &_card{
    width:100%;
    display: flex;
    flex-wrap:wrap;
    padding:10px 0 0 20px;
    &_item{
      width:50%;
      padding:0 20px 20px 0;
      overflow: initial;
      &.screen_all{
        width:100%;
      }
      /deep/.el-card{
        overflow: initial;
        .el-card__body{
          position: relative;
          .header{
            position: absolute;
            left:10px;
            top:-10px;
            background-color: #fff;
            padding:0 10px;
            font-size:16px;
            color:#333;
          }
          .echarts{
            display: flex;
            justify-content: space-between;
            width:100%;
          }
        }
      }
    }
  }
}
.clearfix:before,
  .clearfix:after {
    display: table;
    content: "";
  }
  .clearfix:after {
    clear: both
  }
</style>
